/*
 * @Author: ljkt
 * @Version: 2.0
 * @Date: 2022-05-16 11:06:33
 * @LastEditors: ljkt
 * @LastEditTime: 2025-02-25 22:00:52
 * @Description: UART硬件抽象层
 */

#include "./Hal/MCU_BF7612DM/Hal_Common_Func.h"

#if defined(EN_UART0) || defined(EN_UART1) || defined(EN_UART2) || defined(EN_UART3)

/**
 * @brief 初始化UART硬件
 * @param config UART配置结构体指针
 * @note 配置GPIO引脚并设置UART硬件
 */
void Hal_Uartx_Init(s_uartx_config_t *config)
{
	Hal_Gpio_In(&config->gpio_rx);
	Hal_Gpio_Out(&config->gpio_tx, config->level);

	switch (config->index)
	{
#ifdef EN_UART0
	case e_HAL_UART_0:
		EA = 0;		  // 关总中断；
		UART0_IP_SET; // 设置UART0中断优级为高，根据实际应运设置优先级

		UART0_INT_FLAG_CLR; // 清除UART0中断标志

		UART0_RX_EN_SET(1);		// 接收器使能 ,1为使能，0为禁止
		UART0_MULTI_SET(0);		// 多处理器通信使能,1为使能，0为禁止
		UART0_SEND_MODE_SET(0); // 发送数据模式bit[3]：0：8位模式：1：9位模式模式
		UART0_STOP_MODE_SET(0); // STOP位 ,1为2位STOP，0为1位STOP
		UART0_OD_EN_SET(0);		// 奇偶校验使能 ,1为使能（使用奇偶校验时需开启9位数据模式），0为不使能
		UART0_OD_SET(0);		// 奇偶校验选择 ,1为奇校验，0为偶校验

		UART0_RX_FUN_SET(0); // UART0引脚接收功能使能,0为使能，1为禁止
		UART0_TX_FUN_SET(0); // UART0引脚发送功能使能,0为使能，1为禁止

		UART0_PC_SET(UART0_PAD_CHANGE); // TX/RX引脚功能互换,1为功能互换，0为功能不互换

		UART0_BDL = (uchar)M_HEX_OF_BR(config->baud);						 // 设置波特率=BUSCLK/(16*(UART_BDH[0:1],UART_BDL))
		UART0_CON2 |= (((((uint)(M_HEX_OF_BR(config->baud))) >> 8) & 0x03)); // 设置UART0_BDH[0:1]高两位
		UART0_TX_IE_SET(1);													 // UART0发送中断使能,1为中断使能，0为中断禁止
		UART0_RX_IE_SET(1);													 // UART0接收中断使能,1为中断使能，0为中断禁止

		UART0_PORT_SET(UART0_PORT); // UART0 RX/TX映射选择,0:PA0/PA1;1:PB3/PB4，2/3:PC0/PC1;4:PD6/PA1,5:PD7/PA0；6/7：PD4/PD5

#if (UART0_PORT == UART0_MAP_A) // 0
#if UART0_PAD_CHANGE
		TRISA |= 0x02;	// 设置TX为输入
		TRISA &= ~0x01; // 设置RX为输出
#else
		TRISA &= ~0x02; // 设置TX为输出
		TRISA |= 0x01;	// 设置RX为输入
#endif
#elif (UART0_PORT == UART0_MAP_B) // 1
#if UART0_PAD_CHANGE
		TRISB |= 0x10;	// 设置TX为输入
		TRISB &= ~0x08; // 设置RX为输出
#else
		TRISB &= ~0x10; // 设置TX为输出
		TRISB |= 0x08;	// 设置RX为输入
#endif
#elif (UART0_PORT == UART0_MAP_C) // 6
#if UART0_PAD_CHANGE
		TRISD |= 0x10;	// 设置TX为输入
		TRISD &= ~0x20; // 设置RX为输出
#else
		TRISD &= ~0x10; // 设置TX为输出
		TRISD |= 0x20;	// 设置RX为输入
#endif
#elif (UART0_PORT == UART0_MAP_D) // 2
#if UART0_PAD_CHANGE
		TRISC |= 0x02;	// 设置TX为输入
		TRISC &= ~0x01; // 设置RX为输出
#else
		TRISC &= ~0x02; // 设置TX为输出
		TRISC |= 0x01;	// 设置RX为输入
#endif
#elif (UART0_PORT == UART0_MAP_E) // 4
#if UART0_PAD_CHANGE
		TRISA |= 0x02;	// 设置TX为输入
		TRISD &= ~0x40; // 设置RX为输出
#else
		TRISA &= ~0x02; // 设置TX为输出
		TRISD |= 0x40;	// 设置RX为输入
#endif
#elif (UART0_PORT == UART0_MAP_F) // 5
#if UART0_PAD_CHANGE
		TRISA |= 0x01;	// 设置TX为输入
		TRISD &= ~0x80; // 设置RX为输出
#else
		TRISA &= ~0x01; // 设置TX为输出
		TRISD |= 0x80;	// 设置RX为输入
#endif
#else

#endif

		TI0 = 0;			 // 清除发送中断标志位
		RI0 = 0;			 // 清除接收中断标志位
		UART0_IE_SET;		 // 开UART中断使能
		UART0_MODULE_SET(1); // UAERT0模块开关,1为开，0为关

		EA = 1; // 开总中断
		break;
#endif
#ifdef EN_UART1
	case e_HAL_UART_1:
		EA = 0;				// 关总中断；
		UART1_IP_SET;		// 设置UART1中断优级为高，根据实际应运设置优先级
		UART1_INT_FLAG_CLR; // 清除UART1中断标志

		UART1_RX_EN_SET(1);		// 接收器使能 ,1为使能，0为禁止
		UART1_MULTI_SET(0);		// 多处理器通信使能,1为使能，0为禁止
		UART1_SEND_MODE_SET(0); // 发送数据模式bit[3]：0：八位模式：1：9位模式模式
		UART1_STOP_MODE_SET(0); // STOP位 ,1为2位STOP，0为1位STOP
		UART1_OD_EN_SET(0);		// 奇偶校验使能 ,1为使能（使用奇偶校验时需开启9位数据模式），0为不使能
		UART1_OD_SET(0);		// 奇偶校验选择 ,1为奇校验，0为偶校验

		UART1_RX_FUN_SET(0); // UART1引脚接收功能使能,0为使能，1为禁止
		UART1_TX_FUN_SET(0); // UART1引脚发送功能使能,0为使能，1为禁止

		UART1_PC_SET(UART1_PAD_CHANGE); // TX/RX引脚功能互换,1为功能互换，0为功能不互换

		UART1_BDL = (uchar)M_HEX_OF_BR(config->baud);						 // 设置波特率=BUSCLK/(16*(UART_BDH[0:1],UART_BDL))
		UART1_CON2 |= (((((uint)(M_HEX_OF_BR(config->baud))) >> 8) & 0x03)); // 设置UART1_BDH[0:1]高两位

		UART1_TX_IE_SET(1); // UART1发送中断使能,1为中断使能，0为中断禁止
		UART1_RX_IE_SET(1); // UART1接收中断使能,1为中断使能，0为中断禁止

		UART1_PORT_SET(UART1_PORT); // UART1 RX/TX映射选择,0:PB1/PB2;1:PB6/PB7

#if (UART1_PORT == UART1_MAP_A) // 0
#if UART1_PAD_CHANGE
		TRISB |= 0x04;	// 设置TX为输入
		TRISB &= ~0x02; // 设置RX为输出
#else
		TRISB &= ~0x04; // 设置TX为输出
		TRISB |= 0x02;	// 设置RX为输入
#endif
#elif (UART1_PORT == UART1_MAP_B) // 1
#if UART1_PAD_CHANGE
		TRISB |= 0x80;	// 设置TX为输入
		TRISB &= ~0x40; // 设置RX为输出
#else
		TRISB &= ~0x80; // 设置TX为输出
		TRISB |= 0x40;	// 设置RX为输入
#endif
#else

#endif

		TI1 = 0; // 清除发送中断标志位
		RI1 = 0; // 清除接收中断标志位

		UART1_IE_SET;		 // 开UART中断使能
		UART1_MODULE_SET(1); // UAERT1模块开关,1为开，0为关

		EA = 1; // 开总中断
		break;
#endif
#ifdef EN_UART2
	case e_HAL_UART_2:
		// TODO: 实现UART2波特率和中断配置
		break;
#endif
#ifdef EN_UART3
	case e_HAL_UART_3:
		// TODO: 实现UART3波特率和中断配置
		break;
#endif
	default:
		break;
	}
}

/**
 * @brief 关闭UART硬件
 * @param config UART配置结构体指针
 * @note 重置GPIO配置并禁用UART硬件
 */
void Hal_Uartx_Close(s_uartx_config_t *config)
{
	Hal_Gpio_In(&config->gpio_rx);
	Hal_Gpio_Out(&config->gpio_tx, config->level);
	switch (config->index)
	{
#ifdef EN_UART0
	case e_HAL_UART_0:
		// TODO: 实现UART0关闭序列
		break;
#endif
#ifdef EN_UART1
	case e_HAL_UART_1:
		// TODO: 实现UART1关闭序列
		break;
#endif
#ifdef EN_UART2
	case e_HAL_UART_2:
		// TODO: 实现UART2关闭序列
		break;
#endif
#ifdef EN_UART3
	case e_HAL_UART_3:
		// TODO: 实现UART3关闭序列
		break;
#endif
	default:
		break;
	}
}

/**
 * @brief 通过UART发送单个字节
 * @param config UART配置结构体指针
 * @param dat 要发送的字节
 * @note 此函数是中断安全的
 */
void Hal_Uartx_TxByte_Isr(s_uartx_config_t *config, unsigned char dat)
{
	switch (config->index)
	{
#ifdef EN_UART0
	case e_HAL_UART_0:
		// TODO: 实现UART0发送逻辑
		UART0_BUF = dat;
		break;
#endif
#ifdef EN_UART1
	case e_HAL_UART_1:
		// TODO: 实现UART1发送逻辑
		UART1_BUF = dat;
		break;
#endif
#ifdef EN_UART2
	case e_HAL_UART_2:
		// TODO: 实现UART2发送逻辑
		break;
#endif
#ifdef EN_UART3
	case e_HAL_UART_3:
		// TODO: 实现UART3发送逻辑
		break;
#endif
	default:
		break;
	}
}

/**
 * @brief 通过UART接收单个字节
 * @param config UART配置结构体指针
 * @return 接收到的字节
 * @note 此函数是中断安全的
 */
unsigned char Hal_Uartx_RxByte_Isr(s_uartx_config_t *config)
{
	unsigned char ret = 0;

	switch (config->index)
	{
#ifdef EN_UART0
	case e_HAL_UART_0:
		// TODO: 实现UART0接收逻辑
		ret = UART0_BUF;
		break;
#endif
#ifdef EN_UART1
	case e_HAL_UART_1:
		// TODO: 实现UART1接收逻辑
		ret = UART1_BUF;
		break;
#endif
#ifdef EN_UART2
	case e_HAL_UART_2:
		// TODO: 实现UART2接收逻辑
		break;
#endif
#ifdef EN_UART3
	case e_HAL_UART_3:
		// TODO: 实现UART3接收逻辑
		break;
#endif
	default:
		break;
	}

	return ret;
}

/**
 * @brief 检查UART发送缓冲区是否为空
 * @param config UART配置结构体指针
 * @return 1表示发送缓冲区为空，0表示不为空
 * @note 此函数是中断安全的
 */
unsigned char Hal_Uartx_Get_TxFlag_Isr(s_uartx_config_t *config)
{

	switch (config->index)
	{
#ifdef EN_UART0
	case e_HAL_UART_0:
		// TODO: 实现UART0发送标志检查和清除
		UART0_INT_FLAG_CLR; // 清除UART0中断标志
		if (TI0 == 1)
		{
			UART0_STATE = 0x0F; // 清除发送中断标志位
			return REF_TRUE;
		}
		break;
#endif
#ifdef EN_UART1
	case e_HAL_UART_1:
		// TODO: 实现UART1发送标志检查和清除
		UART1_INT_FLAG_CLR; // 清除UART1中断标志
		if (TI1 == 1)
		{
			UART1_STATE = 0x0F; // 清除发送中断标志位
			return REF_TRUE;
		}
		break;
#endif
#ifdef EN_UART2
	case e_HAL_UART_2:
		// TODO: 实现UART2发送标志检查和清除
		break;
#endif
#ifdef EN_UART3
	case e_HAL_UART_3:
		// TODO: 实现UART3发送标志检查和清除
		break;
#endif
	default:
		break;
	}

	return REF_FALSE;
}

/**
 * @brief 检查UART接收缓冲区是否有数据
 * @param config UART配置结构体指针
 * @return 1表示有数据，0表示无数据
 * @note 此函数是中断安全的，并会清除接收标志
 */
unsigned char Hal_Uartx_Get_RxFlag_Isr(s_uartx_config_t *config)
{
	unsigned char ret = 0;

	switch (config->index)
	{
#ifdef EN_UART0
	case e_HAL_UART_0:
		// TODO: 实现UART0接收标志检查和清除
		UART0_INT_FLAG_CLR; // 清除UART0中断标志
		if (RI0 == 1)
		{
			UART0_STATE = 0x17; // 清除接收中断标志位
			return REF_TRUE;
		}
		break;
#endif
#ifdef EN_UART1
	case e_HAL_UART_1:
		// TODO: 实现UART1接收标志检查和清除
		UART1_INT_FLAG_CLR; // 清除UART1中断标志
		if (RI1 == 1)
		{
			UART1_STATE = 0x17; // 清除接收中断标志位
			return REF_TRUE;
		}
		break;
#endif
#ifdef EN_UART2
	case e_HAL_UART_2:
		// TODO: 实现UART2接收标志检查和清除
		break;
#endif
#ifdef EN_UART3
	case e_HAL_UART_3:
		// TODO: 实现UART3接收标志检查和清除
		break;
#endif
	default:
		break;
	}

	return REF_FALSE;
}

#endif
